﻿using BilibiliDM_PluginFramework;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows.Threading;

namespace MoListv1
{
    class DanmuHandler : INotifyPropertyChanged
    {
        private ObservableCollection<UserListItem> UserList;
        private ObservableCollection<BlackListItem> BlackList;

        private Dispatcher dispatcher;

        public event PropertyChangedEventHandler PropertyChanged;

        public uint MaxTotalItemNum { get => _maxTotalItemCount; set => SetField(ref _maxTotalItemCount, value); }
        private uint _maxTotalItemCount;

        public uint MaxTotalPersonNum { get => _maxTotalPersonCount; set => SetField(ref _maxTotalPersonCount, value); }
        private uint _maxTotalPersonCount;

        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            return true;
        }

        internal DanmuHandler(ObservableCollection<UserListItem> userList, ObservableCollection<BlackListItem> blackList)
        {
            dispatcher = Dispatcher.CurrentDispatcher;
            UserList = userList;
            BlackList = blackList;
        }

        internal void ProcessDanmu(DanmakuModel danmukuModel)
        {
            if (danmukuModel.MsgType != MsgTypeEnum.Comment || string.IsNullOrWhiteSpace(danmukuModel.CommentText))
            {
                return;
            }

            string[] commands = danmukuModel.CommentText.Split(SPLIT_CHAR, StringSplitOptions.RemoveEmptyEntries);
            string rest = string.Join(" ", commands.Skip(1));

            if (danmukuModel.isAdmin)
            {
                switch (commands[0])
                {
                    case "完成":
                        dispatcher.Invoke(() =>
                        {
                            if (UserList.Count > 0)
                            {
                                UserList.RemoveAt(0);
                                Log("完成了,下一个");
                            }
                        });
                        return;
                    case "移除":
                        dispatcher.Invoke(() =>
                        {
                            if (UserList.Remove(new UserListItem(UserListType.Name, rest)))
                            {
                                Log("移除" + rest + "成功");
                            }
                        });
                        return;
                    case "优先":
                        dispatcher.Invoke(() =>
                        {
                            if (UserList.Remove(new UserListItem(UserListType.Name, rest)))
                            {
                                AddUserList(danmukuModel, rest);
                                Log("优先" + rest + "成功");
                            }
                        });
                        return;
                    case "黑名单":
                        dispatcher.Invoke(() =>
                        {
                            AddBlackList(rest);
                        });
                        return;
                    case "解除黑名单":
                        dispatcher.Invoke(() =>
                        {
                            if (BlackList.Remove(new BlackListItem(BlackListType.Name, rest)))
                            {
                                Log("解除" + rest + "黑名单成功");
                            }
                        });
                        return;
                    default:
                        break;
                }
            }
            switch (commands[0])
            {
                case "排队":
                    dispatcher.Invoke(() =>
                    {
                        AddUserList(danmukuModel, rest);
                    });
                    return;
                case "取消排队":
                    dispatcher.Invoke(() =>
                    {
                        if (UserList.Remove(new UserListItem(UserListType.Name, rest)))
                        {
                            Log(danmukuModel.UserName + "取消排队成功");
                        }

                    });
                    return;
                default:
                    break;
            }
        }

        private void AddBlackList(string rest)
        {
            if (dispatcher.Invoke(callback: () => IsInBlackList(rest)))
            {
                Log(rest + "已经在黑名单中");
            }
            else
            {
                BlackList.Add(new BlackListItem(BlackListType.Name, rest));
            }
        }

        private bool IsInBlackList(string username)
        {
            return BlackList.Contains(new BlackListItem(BlackListType.Name, username));
        }

        private void AddUserList(DanmakuModel danmukuModel, string keyword)
        {
            if (dispatcher.Invoke(callback: () => CanAddUser(username: danmukuModel.UserName)))
            {
                dispatcher.Invoke(callback: () =>
                {
                    if (CanAddUser(danmukuModel.UserName))
                    {
                        UserList.Add(new UserListItem(UserListType.Name, keyword));
                    }
                });
            }
        }

        private bool CanAddUser(string username)
        {
            return UserList.Count < MaxTotalItemNum && !IsInBlackList(username) && (UserList.Count(x => x.Content == username) < MaxTotalPersonNum);
        }

        private readonly static char[] SPLIT_CHAR = { ' ' };

        public event LogEvent LogEvent;
        private void Log(string message, Exception exception = null) => LogEvent?.Invoke(this, new LogEventArgs() { Message = message, Exception = exception });
    }
}
